package net.quanter.shield.utils.date;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/***
 * 日期格式化工具类
 * 2020-09-05
 * @author 王老实
 *
 * @since 1.3.13.RELEASE
 */
public class DateFormatter extends DateFormatUtils {

    public static final DateTimeFormatter DATE_FORMAT_STANDARD = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter DATE_FORMAT_STANDARD_SIMPLE = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    public static final DateTimeFormatter DATE_FORMAT_SHORT = DateTimeFormatter.ofPattern("M-d H:m:s");
    public static final DateTimeFormatter DATE_FORMAT_FULL = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS E");
    public static final DateTimeFormatter DATE_FORMAT_FULL_SIMPLE = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
    public static final DateTimeFormatter DATE_FORMAT_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    public static final DateTimeFormatter DATE_FORMAT_YMD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter DATE_FORMAT_YMD_SIMPLE = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static final DateTimeFormatter DATE_FORMAT_YM_SIMPLE = DateTimeFormatter.ofPattern("yyyyMM");
    public static final DateTimeFormatter DATE_FORMAT_MD_SIMPLE = DateTimeFormatter.ofPattern("MMdd");
    public static final DateTimeFormatter DATE_FORMAT_YMDHM_SIMPLE = DateTimeFormatter.ofPattern("yyyyMMddHHmm");

    private static LocalDateTime dateToLocalDateTime(Date date, ZoneId zoneId) {
        return date.toInstant().atZone(zoneId).toLocalDateTime();
    }

    private static LocalDateTime dateToLocalDateTime(long time, ZoneId zoneId) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(time), zoneId);
    }

    /**
     * 默认的format方法
     *
     * @param date Date实例
     * @return formatstr
     */
    public static String format(Date date) {
        return format(date, DATE_FORMAT_STANDARD);
    }

    /**
     * 用默认时区格式化当前时间
     *
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatNow(DateTimeFormatter formatter) {
        ZonedDateTime zdt = ZonedDateTime.now();
        return formatter.format(zdt);
    }

    /**
     * 用GMT时区格式化当前时间
     *
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatNowGMT(DateTimeFormatter formatter) {
        ZonedDateTime zdt = ZonedDateTime.now(TimeZones.GMT_ZONE_ID);
        return formatter.format(zdt);
    }

    /**
     * 用中国格式化当前时间
     *
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatNowChina(DateTimeFormatter formatter) {
        ZonedDateTime zdt = ZonedDateTime.now(TimeZones.CHINA_ZONE_ID);
        return formatter.format(zdt);
    }

    /**
     * 用默认时区格式化时间
     *
     * @param date      Date实例
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String format(Date date, DateTimeFormatter formatter) {
        DateFormatUtils.format(date, "");
        return dateToLocalDateTime(date, TimeZones.DEFAULT_ZONE_ID).format(formatter);
    }

    /**
     * 用默认时区格式化时间
     *
     * @param time      时间戳
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String format(long time, DateTimeFormatter formatter) {
        return formatter.format(dateToLocalDateTime(time, TimeZones.DEFAULT_ZONE_ID));
    }

    /**
     * 用GMT时区格式化时间
     *
     * @param date      Date实例
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatGMT(Date date, DateTimeFormatter formatter) {
        return dateToLocalDateTime(date, TimeZones.GMT_ZONE_ID).format(formatter);
    }

    /**
     * 用GMT时区格式化时间
     *
     * @param time      时间戳
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatGMT(long time, DateTimeFormatter formatter) {
        return formatter.format(dateToLocalDateTime(time, TimeZones.GMT_ZONE_ID));
    }

    /**
     * 用UTC时区格式化时间
     *
     * @param date      Date实例
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatUTC(Date date, DateTimeFormatter formatter) {
        return dateToLocalDateTime(date, TimeZones.UTC_ZONE_ID).format(formatter);
    }

    /**
     * 用UTC时区格式化时间
     *
     * @param time      时间戳
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatUTC(long time, DateTimeFormatter formatter) {
        return formatter.format(dateToLocalDateTime(time, TimeZones.UTC_ZONE_ID));
    }

    /**
     * 用中国时区格式化时间
     *
     * @param date      Date实例
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatChina(Date date, DateTimeFormatter formatter) {
        return dateToLocalDateTime(date, TimeZones.CHINA_ZONE_ID).format(formatter);
    }

    /**
     * 用中国时区格式化时间
     *
     * @param time      时间戳
     * @param formatter 时间格式
     * @return formatstr
     */
    public static String formatChina(long time, DateTimeFormatter formatter) {
        return formatter.format(dateToLocalDateTime(time, TimeZones.CHINA_ZONE_ID));
    }

    /**
     * 解析字符串返回Date实例
     *
     * @param str       时间字符串
     * @param formatter 时间格式
     * @return formatstr
     */
    public static Date parse(String str, DateTimeFormatter formatter) {
        LocalDateTime localDateTime = parseLocalDateTime(str, formatter);
        return Date.from(localDateTime.atZone(TimeZones.DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * 用GMT时区解析字符串返回Date实例
     *
     * @param str       时间字符串
     * @param formatter 时间格式
     * @return formatstr
     */
    public static Date parseGMT(String str, DateTimeFormatter formatter) {
        LocalDateTime localDateTime = parseLocalDateTime(str, formatter);
        return Date.from(localDateTime.atZone(TimeZones.GMT_ZONE_ID).toInstant());
    }

    /**
     * 用UTC时区解析字符串返回Date实例
     *
     * @param str       时间字符串
     * @param formatter 时间格式
     * @return formatstr
     */
    public static Date parseUTC(String str, DateTimeFormatter formatter) {
        LocalDateTime localDateTime = parseLocalDateTime(str, formatter);
        return Date.from(localDateTime.atZone(TimeZones.UTC_ZONE_ID).toInstant());
    }

    /**
     * 用中国时区解析字符串返回Date实例
     *
     * @param str       时间字符串
     * @param formatter 时间格式
     * @return formatstr
     */
    public static Date parseChina(String str, DateTimeFormatter formatter) {
        LocalDateTime localDateTime = parseLocalDateTime(str, formatter);
        return Date.from(localDateTime.atZone(TimeZones.CHINA_ZONE_ID).toInstant());
    }

    private static LocalDateTime parseLocalDateTime(String str, DateTimeFormatter formatter) {
        LocalDateTime localDateTime;
        if (formatter.equals(DateFormatter.DATE_FORMAT_YM_SIMPLE)
            || formatter.equals(DateFormatter.DATE_FORMAT_YMD_SIMPLE)
        ) {
            LocalDate localDate = LocalDate.parse(str, formatter);
            localDateTime = localDate.atStartOfDay();
        } else {
            localDateTime = LocalDateTime.parse(str, formatter);
        }
        return localDateTime;
    }
}
